package com.quan.api.wx.pay;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.quan.commons.core.bean.R;
import com.quan.commons.core.biz.support.MyBaseController;
import com.quan.commons.core.configuration.WxPayConfiguration;
import com.quan.commons.core.properties.SystemValueProperties;
import com.quan.commons.core.properties.WxPayProperties;
import com.quan.commons.core.utils.AmountUtils;
import com.quan.commons.core.utils.IpHelper;
import com.quan.commons.core.utils.OrderUtils;
import com.quan.commons.core.utils.RedisUtils;
import com.quan.mall.commons.constant.MallRabbitMQConstant;
import com.quan.mall.commons.vo.UmsMemberVo;
import com.quan.mall.entity.FmsFinanceCashFlow;
import com.quan.mall.entity.FmsMemberCommisionFreeze;
import com.quan.mall.entity.UmsMember;
import com.quan.mall.entity.UmsMemberLevel;
import com.quan.mall.service.FmsFinanceCashFlowService;
import com.quan.mall.service.FmsMemberCommisionFreezeService;
import com.quan.mall.service.UmsMemberLevelService;
import com.quan.mall.service.UmsMemberService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.text.ParseException;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * 微信支付
 * 会员升级
 */
@Slf4j
@AllArgsConstructor
@RestController
@RequestMapping("/api/wx/upgrade/pay/{appId}")
public class WxUpgradeMemberPayController extends MyBaseController {

	@Autowired
	private SystemValueProperties props;
	
	@Autowired
	private RabbitTemplate rabbitTemplate;

	@Autowired
	private UmsMemberService umsMemberService;

	@Autowired
	private UmsMemberLevelService umsMemberLevelService;

	@Autowired
	private FmsFinanceCashFlowService fmsFinanceCashFlowService;

	@Autowired
	private FmsMemberCommisionFreezeService fmsMemberCommisionFreezeService;

	@Autowired
	private RedisUtils redisOperator;
	
	/**
	 * 预支付交易会话标识
	 * 
	 * @param unifiedOrderRequest
	 * @return
	 */
	@PostMapping(value = "now")
	public Object pay(@PathVariable String appId,
					  @RequestBody WxPayUnifiedOrderRequest unifiedOrderRequest) {

		try {
			final WxPayService wxPayService = WxPayConfiguration.getPayService(appId);
			final WxPayProperties.Config config = WxPayConfiguration.getAppIdConfig(appId);

			log.info("========================>微信支付[升级会员]<========================");
			log.info("==>微信支付商户名：{}", config.getName());
			log.info("==>微信支付商户号：{}", config.getMchId());
			log.info("==>发起时间：{}", LocalDateTime.now());

			String notifyUrl = this.props.getWechat().getUpgradePayNotifyUrl();

			unifiedOrderRequest.setSpbillCreateIp(IpHelper.getIpAddr(request));
			unifiedOrderRequest.setNotifyUrl(notifyUrl.replace("{appId}", appId));
			unifiedOrderRequest.setTradeType(WxPayConstants.TradeType.JSAPI);

			Object createOrder = wxPayService.createOrder(unifiedOrderRequest);
			log.info("==>创建”预支付交易会话标识“成功，等待用户支付");
			
			return R.ok().put("data", createOrder);

		} catch (Exception e) {
			log.error("==>创建”预支付交易会话标识“失败，错误信息：{}", e.getMessage());
		}
		return R.failure("微信支付：创建”预支付交易会话标识“失败");
	}

	/**
	 * 支付回调通知处理
	 * 
	 * @param xmlData
	 * @return
	 * @throws WxPayException
	 * @throws ParseException
	 */
	@PostMapping("notify")
	public String parseOrderNotifyResult(
				@RequestBody String xmlData,
				@PathVariable String appId
				) throws WxPayException, ParseException {
		log.info("==>微信支付，回调通知，会员升级处理");

		final WxPayService wxPayService = WxPayConfiguration.getPayService(appId);

		WxPayOrderNotifyResult result = wxPayService.parseOrderNotifyResult(xmlData);

		final String upgradeJson = this.redisOperator.get("mall:member:upgrade:" + result.getOutTradeNo());
		final JSONObject jsonObject = JSON.parseObject(upgradeJson);

		final Long memberId = (Long) jsonObject.get("memberId");
		final Integer levelId = (Integer) jsonObject.get("levelId");

		// 升级前的
		final UmsMember umsMemberOld = this.umsMemberService.getById(memberId);
		final UmsMemberLevel levelOld = this.umsMemberLevelService.getById(umsMemberOld.getLevelId());

		// 升级
		final UmsMemberVo member = this.umsMemberService.upgradeMember(memberId, levelId.longValue());
		final UmsMemberLevel level = this.umsMemberLevelService.getById(levelId);

		log.info("会员升级成功，会员：{}, 级别：{}->{}", member.getNickname(), levelOld.getName(), level.getName());

		// 涉及佣金计算：注册成为会员后，推荐的其他用户注册会员，可获50%会员费提成
		// 获取当前会员的上级会员，并且判断当前会员是否首次升级（首次才有会员费提成，并且上级是会员）
		// 获取上级会员
		if(null != member.getRefereeMemberId()) {
			log.info("计算上级会员提成费");

			if(member.getUpgradeCount() <= 1) {
				final UmsMember refereeMember = this.umsMemberService.getById(member.getRefereeMemberId());
				final UmsMemberLevel refereeMemberLevel = this.umsMemberLevelService.getById(refereeMember.getLevelId());
				// 判断级别：普通会员，vip会员，业务代理才有会员提成费
				if(refereeMemberLevel.getLevel() == 2 || refereeMemberLevel.getLevel() == 3 || refereeMemberLevel.getLevel() == 4) {
					// 计算会员提成费用，给到上级会员：当前会员升级的费用 * 会员费提成百分比
					// 990（当前会员升级费用） * (50 / 100)=0.5（会员提成费%） = 495
					final BigDecimal payFee = AmountUtils.changeF2Y(new BigDecimal(result.getTotalFee().toString()));
					log.info("当前会员升级的费用：{}", payFee);
					final BigDecimal ratio = new BigDecimal(level.getDeduct().toString()).divide(new BigDecimal("100"));
					log.info("提成比例：{}", ratio);
					BigDecimal deductAmount = payFee.multiply(ratio).setScale(2, BigDecimal.ROUND_DOWN);
					log.info("上级会员提成金额：{}", deductAmount);

					// 记录到佣金冻结表
					FmsMemberCommisionFreeze cz = new FmsMemberCommisionFreeze();
					// 资金类型：1->推广佣金，2->分销佣金
					cz.setBankrollType(1);
					cz.setMemberId(refereeMember.getId());
					cz.setMemberName(refereeMember.getNickname());
					cz.setSubMemberId(member.getId());
					cz.setSubMemberName(member.getNickname());
					// 状态：1->待到账，2->已到账，3->锁定（用户申请退款，防止退款时间超过14天），4->已取消(用户14天内申请退款，佣金扣除不到账)
					cz.setStatus(1);
					cz.setCommissionPercent(ratio);
					cz.setFreezeAmount(deductAmount);
					// 是否可提现：1->可提现，2->不可提现
					cz.setIsWithdraw(1);
					cz.setRemarks("会员升级提成，升级会员：["+member.getNickname()+"]，级别：["+level.getName()+"]，升级费用：["+payFee+"]");
					this.fmsMemberCommisionFreezeService.save(cz);


				} else {
					log.info("上级会员未达到级别无法获取会员升级提成费，上级会员级别：" + refereeMemberLevel.getName());
				}
			} else {
				log.info("当前会员非首次升级，不在计算会员提成费");
			}
		}


		FmsFinanceCashFlow cashFlow = new FmsFinanceCashFlow();
		cashFlow.setOpenId(result.getOpenid());
		cashFlow.setAppId(result.getAppid());
		cashFlow.setMchId(result.getMchId());
		cashFlow.setMemberId(member.getId());
		cashFlow.setMemberName(member.getNickname());
		cashFlow.setTransactionId(result.getTransactionId());


		// 订单支付
		cashFlow.setTransactionType(3);
		cashFlow.setAmount(AmountUtils.changeF2Y(new BigDecimal(result.getTotalFee())));
		if(levelOld.getId() == level.getId()) {
			cashFlow.setRemarks("会员续费：级别["+level.getName()+"]");
		} else {
			cashFlow.setRemarks("会员升级：["+levelOld.getName()+"]升级为["+level.getName()+"]");
		}


		Map<String, Object> extraMap = new HashMap<String, Object>();
		cashFlow.setExtraJson(JSON.toJSONString(extraMap));

		this.fmsFinanceCashFlowService.save(cashFlow);

		// 处理完成，删除缓存中的会员升级信息
		this.redisOperator.del("mall:member:upgrade:" + result.getOutTradeNo());

		return WxPayNotifyResponse.success("成功");
	}

}
